import json

from client.ApiClient import client
from common import constants
from config.dynamic_configuration import ConfigCenter
from service.CallCore import tool_map
from service.ToolSchema import tools


class CallService:

    @classmethod
    def call_entrance(cls, messages) -> str:
        choice = None
        finish_reason = None

        while finish_reason is None or finish_reason == constants.FINISH_REASON:

            completion = client.chat.completions.create(
                model=ConfigCenter.get_model(),
                messages=messages,
                temperature=0.3,
                tools=tools,
            )

            # 判断 AI 是否返回了参数内容
            choice = completion.choices[0]
            finish_reason = choice.finish_reason
            if finish_reason == constants.FINISH_REASON:

                # 将 Kimi 大模型返回的 assistant 消息也添加到上下文中，以便于下次请求时 Kimi 大模型能理解我们的诉求
                messages.append(choice.message)

                # tool_calls 可能是多个，因此我们使用循环逐个执行
                for tool_call in choice.message.tool_calls:
                    # 获取接口名
                    tool_call_name = tool_call.function.name

                    # 获取调用接口的参数
                    tool_call_arguments = json.loads(tool_call.function.arguments)

                    # 通过 tool_map 快速找到需要执行哪个函数
                    tool_function = tool_map[tool_call_name]
                    tool_result = tool_function(tool_call_arguments)

                    # 使用函数执行结果构造一个 role=tool 的 message，以此来向模型展示工具调用的结果；
                    # 注意，我们需要在 message 中提供 tool_call_id 和 name 字段，以便 Kimi 大模型
                    # 能正确匹配到对应的 tool_call。
                    # 我们约定使用字符串格式向 Kimi 大模型提交工具调用结果，因此在这里使用 json.dumps 将执行结果序列化成字符串
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "name": tool_call_name,
                        "content": json.dumps(tool_result),
                    })

        # 在这里，我们才将模型生成的回复返回给用户
        return choice.message.content
